#pragma once

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>

// 使用空格代表分隔符
const std::string blank_space_sep = " ";
const std::string protocol_sep = "\n";

std::string Encode(const std::string &content) // 封装报文
{
    std::string package = std::to_string(content.size());
    package += protocol_sep;
    package += content;
    package += protocol_sep;

    return package;
}

// "len"\n"x op y"\n
bool Decode(std::string &package, std::string *content) // 转码
{
    // 找到字符串中的\n
    std::size_t pos = package.find(protocol_sep);
    if (pos == std::string::npos) // 如果没有找到\n就直接返回false
        return false;

    // 进行字符串的拼接
    std::string len_str = package.substr(0, pos);
    std::size_t len = std::stoi(len_str);

    // package = len_str + content_str + 2，报头等于字符串长度加上两个空格符
    std::size_t total_len = len_str.size() + len + 2;
    if (package.size() < total_len)
        return false;

    // 提出有效的报文
    *content = package.substr(pos + 1, len);

    // earse 移除报文 package.erase(0, total_len);
    package.erase(0, total_len);

    return true;
}

class Request
{
public:
    Request(int data1, int data2, char oper) : x(data1), y(data2), op(oper)
    {
    }

    Request()
    {
    }

public:
    bool Serialize(std::string *out) // 序列化，struct=>string
    {
        // 构建报文的有效载荷
        // x op y -> "x op y"
        // 我们实现\n区分 "x op y" \n "a op b"
        std::string s = std::to_string(x);
        s += blank_space_sep;
        s += op;
        s += blank_space_sep;
        s += std::to_string(y);

        // 封装报头
        //*out = std::to_string(s.size());
        //*out += protocol_sep;
        //*out += s;
        *out = s;
        return true;
    }

    bool Deserialize(const std::string &in) // 反序列化，string=>struct
    {
        // "len"\n"x op y"
        // 找是否含有空格键，"x op y"可以找到前一个空格符号或者后一个空格符号
        // 现在将一个长的字符串转换为三个短字符串
        // "x op y" 找到op前的空字符
        std::size_t left = in.find(blank_space_sep);
        if (left == std::string::npos)
            return false;
        std::string part_x = in.substr(0, left);

        // "x op y" 找到op后的空字符
        std::size_t right = in.rfind(blank_space_sep);
        if (right == std::string::npos)
            return false;
        std::string part_y = in.substr(right + 1);

        if (left + 2 != right)
            return false;
        op = in[left + 1];
        x = std::stoi(part_x);
        y = std::stoi(part_y);
        return true;
    }

    void DebugPrint()
    {
        std::cout << "新请求构建完成:  " << x << op << y << "=?" << std::endl;
    }

public:
    // x op y
    int x;
    int y;
    char op;
};

class Response
{
public:
    Response(int res, int c) : result(res), code(c)
    {
    }

    Response()
    {
    }

public:
    bool Serialize(std::string *out)
    {
        // "len"\n"result code"
        // 构建报文的有效载荷
        std::string s = std::to_string(result);
        s += blank_space_sep;
        s += std::to_string(code);

        // 封装报头
        //*out = std::to_string(s.size());
        //*out += protocol_sep;
        //*out += s;
        *out = s;
        return true;
    }

    bool Deserialize(const std::string &in)
    {
        std::size_t pos = in.find(blank_space_sep);
        if (pos == std::string::npos)
            return false;

        std::string part_left = in.substr(0, pos);
        std::string part_right = in.substr(pos + 1);

        result = std::stoi(part_left);
        code = std::stoi(part_right);

        return true;
    }

    void DebugPrint()
    {
        std::cout << "结果响应完成, result: " << result << ", code: " << code << std::endl;
    }

public:
    int result;
    int code; // 0 可信，否则具体是几，就表示什么类型的错误
};